package com.matrix.framework.core.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import org.springframework.web.reactive.config.CorsRegistry;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * CORS跨域配置类
 * 
 * 提供灵活的跨域配置，支持从配置文件读取配置参数，
 * 支持根据环境动态启用或禁用CORS功能，确保不同环境下的安全性和可维护性
 *
 * Copyright © 海平面工作室 版权所有
 *
 * @Author: Leo
 * @Create: 2024/10/3 11:15
 * @Since 1.2
 */
@Configuration
@EnableConfigurationProperties(MatrixCorsConfig.CorsProperties.class)
public class MatrixCorsConfig {

    private final CorsProperties corsProperties;

    public MatrixCorsConfig(CorsProperties corsProperties) {
        this.corsProperties = corsProperties;
    }

    @Bean
    public CorsWebFilter corsWebFilter() {
        System.out.println("=== CORS Configuration Debug ===");
        System.out.println("CORS Enabled: " + corsProperties.getEnabled());
        System.out.println("Allowed Origins: " + corsProperties.getAllowedOrigins());
        System.out.println("Allowed Methods: " + corsProperties.getAllowedMethods());
        System.out.println("Allow Credentials: " + corsProperties.getAllowCredentials());
        
        CorsConfiguration configuration = new CorsConfiguration();
        
        if (corsProperties.getEnabled()) {
            // 设置允许的源 - 解析逗号分隔的字符串
            if (corsProperties.getAllowedOrigins() != null && !corsProperties.getAllowedOrigins().isEmpty()) {
                List<String> origins = Arrays.stream(corsProperties.getAllowedOrigins().split(","))
                        .map(String::trim)
                        .filter(origin -> !origin.isEmpty())
                        .collect(Collectors.toList());
                
                if (!origins.isEmpty()) {
                    configuration.setAllowedOrigins(origins);
                } else {
                    // 如果解析后为空，拒绝所有跨域请求
                    configuration.setAllowedOrigins(Collections.emptyList());
                }
            } else {
                // 如果没有配置允许的源，拒绝所有跨域请求
                configuration.setAllowedOrigins(Collections.emptyList());
            }
            
            // 设置允许的方法
            if (corsProperties.getAllowedMethods() != null && !corsProperties.getAllowedMethods().isEmpty()) {
                List<String> methods = Arrays.stream(corsProperties.getAllowedMethods().split(","))
                        .map(String::trim)
                        .filter(method -> !method.isEmpty())
                        .collect(Collectors.toList());
                configuration.setAllowedMethods(methods);
            } else {
                // 默认允许的方法
                configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS", "HEAD"));
            }
            
            // 设置允许的头
            if (corsProperties.getAllowedHeaders() != null && !corsProperties.getAllowedHeaders().isEmpty()) {
                List<String> headers = Arrays.stream(corsProperties.getAllowedHeaders().split(","))
                        .map(String::trim)
                        .filter(header -> !header.isEmpty())
                        .collect(Collectors.toList());
                configuration.setAllowedHeaders(headers);
            } else {
                // 默认允许的头
                configuration.setAllowedHeaders(Arrays.asList("Origin", "Content-Type", "Accept", "Authorization", "X-Requested-With"));
            }
            
            // 设置是否允许凭证
            configuration.setAllowCredentials(corsProperties.getAllowCredentials());
            
            // 设置预检请求的缓存时间
            configuration.setMaxAge(corsProperties.getMaxAge());
        } else {
            // 如果CORS未启用，设置为拒绝所有跨域请求
            configuration.setAllowedOrigins(Collections.emptyList());
            configuration.setAllowedMethods(Collections.emptyList());
            configuration.setAllowedHeaders(Collections.emptyList());
            configuration.setAllowCredentials(false);
        }
        
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        
        return new CorsWebFilter(source);
    }

    public void addCorsMappings(CorsRegistry corsRegistry) {
    }

    /**
     * CORS配置属性类
     */
    @ConfigurationProperties(prefix = "matrix.cors")
    public static class CorsProperties {
        
        /**
         * 是否启用CORS功能
         */
        private Boolean enabled = false;
        
        /**
         * 允许的前端地址，多个地址用逗号分隔
         */
        private String allowedOrigins = "http://localhost:5666";
        
        /**
         * 允许的HTTP方法，多个方法用逗号分隔
         */
        private String allowedMethods = "GET,POST,PUT,DELETE,OPTIONS,HEAD";
        
        /**
         * 允许的请求头，多个头部用逗号分隔
         */
        private String allowedHeaders = "Origin,Content-Type,Accept,Authorization,X-Requested-With";
        
        /**
         * 是否允许携带凭证（如Cookie）
         */
        private Boolean allowCredentials = true;
        
        /**
         * 预检请求的缓存时间（秒）
         */
        private Long maxAge = 3600L;

        // Getter and Setter methods
        public Boolean getEnabled() {
            return enabled;
        }

        public void setEnabled(Boolean enabled) {
            this.enabled = enabled;
        }

        public String getAllowedOrigins() {
            return allowedOrigins;
        }

        public void setAllowedOrigins(String allowedOrigins) {
            this.allowedOrigins = allowedOrigins;
        }

        public String getAllowedMethods() {
            return allowedMethods;
        }

        public void setAllowedMethods(String allowedMethods) {
            this.allowedMethods = allowedMethods;
        }

        public String getAllowedHeaders() {
            return allowedHeaders;
        }

        public void setAllowedHeaders(String allowedHeaders) {
            this.allowedHeaders = allowedHeaders;
        }

        public Boolean getAllowCredentials() {
            return allowCredentials;
        }

        public void setAllowCredentials(Boolean allowCredentials) {
            this.allowCredentials = allowCredentials;
        }

        public Long getMaxAge() {
            return maxAge;
        }

        public void setMaxAge(Long maxAge) {
            this.maxAge = maxAge;
        }
    }
}
